﻿namespace EAL.ViewModels
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Data;
    using EAL.Database;
    using EAL.Models;
    using EAL.MVVM;
    using Microsoft.Win32;

    public class ProductsVM : TabItemVM
    {
        #region private fields

        private Product selectedProduct;

        private ObservableCollection<Product> products = new ObservableCollection<Product>();

        private String search;

        private bool isActive;

        private RelayCommand add;
        private RelayCommand edit;
        private RelayCommand delete;

        #endregion

        #region Properties

        public Product SelectedProduct
        {
            get 
            { 
                return selectedProduct; 
            }
            set 
            {   
                selectedProduct = value;
                if (this.delete != null)
                {
                    this.delete.RaiseCanExecuteChanged();
                    this.edit.RaiseCanExecuteChanged();
                }               
            }
        }

        public String Search
        {
            get
            {
                return this.search;
            }
            set
            {
                this.search = value;

                this.ProductsViewCollection.Refresh();
            }
        }

        public RelayCommand Add
        {
            get
            {
                if (this.add == null)
                {
                    this.add = new RelayCommand(this.AddProducte);
                }
                return this.add;
            }
        }

        public RelayCommand Edit
        {
            get
            {
                if (this.edit == null)
                {
                    this.edit = new RelayCommand(
                        this.EditProducte,
                        (o) => this.SelectedProduct != null
                    );
                }
                return this.edit;
            }
        }        

        public RelayCommand Delete
        {
            get 
            {
                if (this.delete == null)
                {
                    this.delete = new RelayCommand(
                        this.DeleteProducte,
                        (o) => this.SelectedProduct != null && !(this.DbContext.Positions.Where<Position>(p => p.Product.Id == this.SelectedProduct.Id).Count() > 0)
                    );
                }
                return this.delete;
            }
        }
        
        public ICollectionView ProductsViewCollection { get; protected set; }        
                
        // is needet to update view on TabItem-Change
        public bool IsActive
        {
            get
            {
                return this.isActive;
            }
            set
            {
                this.isActive = value;
                if (this.isActive)
                {
                    this.products.Clear();
                    this.InitializeDatabasePackages();
                }
            }
        }

        public DbContext DbContext { get; set; }

        #endregion

        #region Constructor

        public ProductsVM()
        {
            this.ExportCommandDescription = "Produkte exportieren";
            this.ImportCommandDescription = "Produkte importiern";
            this.ExportCommand = new RelayCommand(ExportProductes);
            this.ImportCommand = new RelayCommand(ImportProductes);


            this.ProductsViewCollection = CollectionViewSource.GetDefaultView(this.products);

            this.ProductsViewCollection.Filter = this.CheckProductForVisability;

            if (DesignerProperties.GetIsInDesignMode(new FrameworkElement()))
            {
                this.InitializeDesignerPackages();
            }
        }
        
        #endregion

        #region Products-Initializing

        private void InitializeDatabasePackages()
        {       
            foreach (Product product in this.DbContext.Products)
            {
                this.products.Add(product);
            }
        }

        private void InitializeDesignerPackages()
        {
            this.products.Add(new Product() { Id = 1, Name = "Produkt 1", Price = 99.95m });
            this.products.Add(new Product() { Id = 99, Name = "Produkt 2", Price = 4.95m });
            this.products.Add(new Product() { Id = 678, Name = "Produkt 3", Price = 1.95m });
            this.products.Add(new Product() { Id = 4, Name = "Produkt 4", Price = 159.95m });
        }
        
        #endregion

        #region Command-Callbacks

        private void DeleteProducte(object sender)
        {
            this.DbContext.Products.Remove(this.SelectedProduct);
            this.DbContext.SaveChanges();

            this.products.Remove(this.SelectedProduct);
        }

        private void AddProducte(object sender)
        {
            Product product = new Product();

            ProductWindow pw = new ProductWindow(this.DbContext, ref product);

            if (pw.ShowDialog() == true && product.Name != null)
            {
                this.products.Add(product);
                this.DbContext.Products.Add(product);
                this.DbContext.SaveChanges();
            }
        }

        private void EditProducte(object sender)
        {
            ProductWindow pw = new ProductWindow(this.DbContext, ref this.selectedProduct);

            if (pw.ShowDialog() == true && this.selectedProduct.Name != null)
            {
                this.DbContext.SaveChanges();
            }
            else
            {
                this.DbContext.Entry<Product>(this.selectedProduct).Reload();
            }
        }

        private void ExportProductes(object sender)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.DefaultExt = ".csv";
            dialog.Filter = "CSV Datei (.csv)|*.csv";
            dialog.FileName = "EAL-Produkt-Export_" + DateTime.Now.ToString("MM-yy");

            if (dialog.ShowDialog() == true)
            {
                try 
	            {
                    Misc.CsvHandler.writeCsv<Product>(dialog.FileName, this.products);
	            }
	            catch (Exception)
	            {
		            MessageBox.Show("Beim exportieren ist ein Fehler aufgetreten.", " Export fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
	            }
            }
        }

        private void ImportProductes(object sender)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.DefaultExt = ".csv";
            dialog.Filter = "CSV Datei (.csv)|*.csv";
            dialog.Multiselect = false;

            if (dialog.ShowDialog() == true)
            {
                try
                {
                    foreach (Product product in Misc.CsvHandler.readCsv<Product>(dialog.FileName))
                    {
                        this.products.Add(product);
                        this.DbContext.Products.Add(product);
                    }
                    this.DbContext.SaveChanges();
                }
                catch (Exception)
                {
                    MessageBox.Show("Beim importieren ist ein Fehler aufgetreten.", " Import fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
                
        #endregion

        #region Other Functions

        private bool CheckProductForVisability(object sender)
        {
            if (!String.IsNullOrWhiteSpace(this.Search))
            {
                Product product = sender as Product;

                return (product.Name.Contains(this.Search) || product.Id.ToString().StartsWith(this.Search));
            }
            return true;
        }

        #endregion
    }
}
